package sanshui.system.trade.util;

import sanshui.system.trade.factory.data.Bar;

import java.util.ArrayList;
import java.util.List;

/**
 * 指标工具
 */
public class IndicatorUtil {

    public static List<Long> MAn(List<Bar> target, Integer n){
        return IndicatorUtil.MAn(IndicatorUtil.parseBar2LongClose(target), n);
    }

    public static List<Long> MAn(List<Long> target, int n) {
        List<Long> targetTemp = new ArrayList<>();
        List<Long> rsl = new ArrayList<>();

        if (target == null || target.size() == 0 || n <= 1) {
            return rsl;
        }

        if (target.size() < n) {
            return target;
        }

        for (Long item : target) {
            if (targetTemp.size() == n) {
                targetTemp.remove(0);
                targetTemp.add(item);
                rsl.add(IndicatorUtil._MAn(targetTemp, n));
            }
            if (targetTemp.size() < n) {
                targetTemp.add(item);
                if (targetTemp.size() == n) {
                    rsl.add(IndicatorUtil._MAn(targetTemp, n));
                } else {
                    rsl.add(item);
                }
            }
        }
        return rsl;
    }

    public static Long _MAn(List<Long> target, int n) {
        Long sum = 0L;

        if (target.size() != n) {
            return sum;
        } else {
            for (Long item : target) {
                sum += + item;
            }
        }
        return sum/n;
    }

    public  static List<Long> EMAn(List<Long> target, int n){
        List<Long> rsl = new ArrayList<>();

        if (target == null || target.size() == 0 || n <= 1) {
            return rsl;
        }
        if (target.size() < n) {
            return target;
        }
        Long pre = null;
        for (Long item : target) {
            pre = IndicatorUtil._EMAn(item, n, pre);
            if (rsl.size() >= n){
                rsl.remove(0);
            }
            rsl.add(pre);
        }
        return rsl;
    }

    public static Long _EMAn(Long target, int n, Long pre) {
        if (n < 1) {
            return 0L;
        }
        if (pre == null || 0L == pre){
            return target;
        }
        Long multiply = target * 2;
        Long multiply1 = pre * (n - 1);
        Long add = multiply + multiply1;
        return add/(n + 1);
    }

//    public static boolean t1CrossT2(Long t1, Long t1Pre, Long t2, Long t2Pre){
//        return t1.compareTo(t2) >= 0 && t1Pre.compareTo(t2Pre) < 0;
//    }

    public static boolean t1UpCrossT2(Long t1, Long t1Pre, Long t2, Long t2Pre, boolean reverse){
        if (reverse){
            return !(t1.compareTo(t2) >= 0 && t1Pre.compareTo(t2Pre) < 0);
        } else {
            return t1.compareTo(t2) >= 0 && t1Pre.compareTo(t2Pre) < 0;
        }
    }

    public static List<String> parseLong2Str(List<Long> data){
        List<String> strs = new ArrayList<>();
        for (Long datum : data) {
            strs.add(datum.toString());
        }
        return strs;
    }

    public static List<Long> parseBar2LongClose(List<Bar> data){
        List<Long> strs = new ArrayList<>();
        for (Bar datum : data) {
            strs.add(datum.close);
        }
        return strs;
    }

    public static Long calculateTR(Bar previous, Bar current){
        return Math.max(current.high - current.low,
                Math.max(Math.abs(current.high - previous.close), Math.abs(current.low - previous.close)));
    }

    // 计算 ATR（平均真实波动范围）
    public static List<Long> calculateATRList(int period, List<Long> hisATR) {
        Long atr = calculateATR(period, hisATR);
        if (hisATR.size() < period){
            hisATR.add(atr);
        } else {
            hisATR.remove(0);
            hisATR.add(atr);
        }
        return hisATR;
    }

    // 计算 ATR（平均真实波动范围）
    public static Long calculateATR(int period, List<Long> hisATR) {
        Long sum = 0L;
        int startIndex = Math.max(0, hisATR.size() - period);
        for (int i = startIndex; i < hisATR.size(); i++) {
            sum += hisATR.get(i);
        }
        return sum / (hisATR.size() - startIndex);
    }

    // 计算指定窗口内的最高值
    public static double calculateMaxHigh(int window, List<Bar> data) {
        double maxHigh = Double.MIN_VALUE;
        for (int i = data.size()-window; i < data.size(); i++) {
            if (data.get(i).high > maxHigh) {
                maxHigh = data.get(i).high;
            }
        }
        return maxHigh;
    }

    // 计算指定窗口内的最低值
    public static double calculateMinLow(int window, List<Bar> data) {
        double minLow = Double.MAX_VALUE;
        for (int i = data.size()-window; i < data.size(); i++) {
            if (data.get(i).low < minLow) {
                minLow = data.get(i).low;
            }
        }
        return minLow;
    }
}
